package cn.iocoder.yudao.module.system.convert.oauth2;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.Oauth2OpenAccessTokenRespVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.Oauth2OpenAuthorizeInfoRespVO;
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.Oauth2OpenCheckTokenRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.Oauth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.Oauth2ApproveDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.Oauth2ClientDO;
import cn.iocoder.yudao.module.system.util.oauth2.Oauth2Utils;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * oauth2开放转换
 *
 * @author huangweidong
 * @date 2023/05/09
 */
@Mapper
public interface Oauth2OpenConvert {

    Oauth2OpenConvert INSTANCE = Mappers.getMapper(Oauth2OpenConvert.class);

    /**
     * 转换
     *
     * @param bean bean
     * @return {@code Oauth2OpenAccessTokenRespVO}
     */
    default Oauth2OpenAccessTokenRespVO convert(Oauth2AccessTokenDO bean) {
        Oauth2OpenAccessTokenRespVO respVO = convert0(bean);
        respVO.setTokenType(SecurityFrameworkUtils.AUTHORIZATION_BEARER.toLowerCase());
        respVO.setExpiresIn(Oauth2Utils.getExpiresIn(bean.getExpiresTime()));
        respVO.setScope(Oauth2Utils.buildScopeStr(bean.getScopes()));
        return respVO;
    }

    /**
     * convert0
     *
     * @param bean bean
     * @return {@code Oauth2OpenAccessTokenRespVO}
     */
    Oauth2OpenAccessTokenRespVO convert0(Oauth2AccessTokenDO bean);

    /**
     * convert2
     *
     * @param bean bean
     * @return {@code Oauth2OpenCheckTokenRespVO}
     */
    default Oauth2OpenCheckTokenRespVO convert2(Oauth2AccessTokenDO bean) {
        Oauth2OpenCheckTokenRespVO respVO = convert3(bean);
        respVO.setExp(LocalDateTimeUtil.toEpochMilli(bean.getExpiresTime()) / 1000L);
        respVO.setUserType(UserTypeEnum.ADMIN.getValue());
        return respVO;
    }

    /**
     * convert3
     *
     * @param bean bean
     * @return {@code Oauth2OpenCheckTokenRespVO}
     */
    Oauth2OpenCheckTokenRespVO convert3(Oauth2AccessTokenDO bean);

    /**
     * 转换
     *
     * @param client   客户端
     * @param approves 批准
     * @return {@code Oauth2OpenAuthorizeInfoRespVO}
     */
    default Oauth2OpenAuthorizeInfoRespVO convert(Oauth2ClientDO client, List<Oauth2ApproveDO> approves) {
        // 构建 scopes
        List<KeyValue<String, Boolean>> scopes = new ArrayList<>(client.getScopes().size());
        Map<String, Oauth2ApproveDO> approveMap = CollectionUtils.convertMap(approves, Oauth2ApproveDO::getScope);
        client.getScopes().forEach(scope -> {
            Oauth2ApproveDO approve = approveMap.get(scope);
            scopes.add(new KeyValue<>(scope, approve != null ? approve.getApproved() : false));
        });
        // 拼接返回
        return new Oauth2OpenAuthorizeInfoRespVO(
                new Oauth2OpenAuthorizeInfoRespVO.Client(client.getName(), client.getLogo()), scopes);
    }

}
